package com.example.demo.demo.clone;

import lombok.Data;

@Data
public class HashTable implements Cloneable{
    private Entry[] buckets;
    @Data
    private static class Entry {
        final Object key;
        Object value;
        Entry next;

        public Entry(Object key, Object value, Entry next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        Entry deepCopy() {
//            return new Entry(key, value, next == null ? null : next.deepCopy()); // 递归
            Entry result = new Entry(key, value, next);
            for (Entry p = result; p.next != null; p = p.next) {
                p.next = new Entry(p.next.key, p.next.value, p.next.next);
            }
            return result;// 迭代
        }

    }

    public HashTable() {

    }

    // 最好使用拷贝构造器或拷贝静态工厂来实现对象的拷贝
    public HashTable(HashTable hashTable) { // 拷贝构造器
        // ...
    }

    public static HashTable newInstance(HashTable hashTable) { // 拷贝工厂
        // ...
        return new HashTable();
    }

    @Override
    protected HashTable clone() {
        try {
            HashTable clone = (HashTable) super.clone();
            clone.buckets = new Entry[buckets.length];
            for (int i = 0; i < buckets.length; i++) { // 单独拷贝
                if (buckets[i] != null) {
                    clone.buckets[i] = buckets[i].deepCopy();
                }
            }
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }

    public static void main(String[] args) {
        Entry[] entries = new Entry[3];
        Entry entry3 = new Entry(3, 4, null);
        Entry entry2 = new Entry(2, 3, entry3);
        Entry entry1 = new Entry(1, 2, entry2);
        entries[0] = entry1;
        entries[1] = entry2;
        entries[2] = entry3;

        HashTable hashTable = new HashTable();
        hashTable.setBuckets(entries);

        System.out.println(hashTable);
        HashTable clone = hashTable.clone();
        System.out.println(clone);
    }
}
